package com.xjrh.traintravel.collector.netty.handler;

import com.xjrh.common.core.domain.BaseEntity;
import com.xjrh.traintravel.collector.common.CRC16M;
import com.xjrh.traintravel.collector.common.CodeConvertor;
import com.xjrh.traintravel.collector.common.ResultData;
import com.xjrh.traintravel.collector.common.StringUtil;
import com.xjrh.traintravel.collector.netty.coder.command.AgreementCommandEnum;
import com.xjrh.traintravel.collector.netty.command.config.*;
import com.xjrh.traintravel.collector.netty.coder.command.AgreementConstant;
import com.xjrh.traintravel.collector.netty.coder.command.AgreementStructure;
import com.xjrh.traintravel.collector.pojo.config.*;
import com.xjrh.traintravel.collector.runner.NettyClientManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Calendar;

/**
 * 参数设置指令处理类
 *
 * @author snps
 * @create 2022-01-27 11:53
 * @describe
 **/
@Component
@Slf4j
public class ConfigHandler extends BaseAgreementHandler {

    @Resource
    private NettyClientManager nettyClientManager;


    /**
     * 根据命令编号，创建命令
     * @param commandNo 子命令编号
     * @param config 配置信息Vo
     * @return AgreementStructure
     */
    public AgreementStructure buildCommand(String commandNo, BaseEntity config) {
        AgreementStructure agreement = null;

        // 配置-主机信息
        if (commandNo.equals("01")) {
            return agreement = buildInfo((InfoConfig) config);
        }
        // 配置-采集策略
        if (commandNo.equals("02")) {
            return agreement = buildCollectionStrategy((CollectionStrategyConfig) config);
        }
        // 配置-故障分级
        if (commandNo.equals("03")) {
            return agreement = buildFaultGrade((FaultGradeConfig) config);
        }
        // 配置-系统时间
        if (commandNo.equals("04")) {
            return agreement = buildSystemTime((SystemTimeConfig) config);
        }
        // 配置-波磨设置
        if (commandNo.equals("05")) {
            return agreement = buildCorrugation((CorrugationConfig) config);
        }
        // 配置-心跳设置
        if (commandNo.equals("06")) {
            return agreement = buildHeartbeat((HeartbeatConfig) config);
        }
        // 配置-前置采集重置
        if (commandNo.equals("0A")) {
            return agreement = buildConfigOA((Config0A) config);
        }
        // 配置-上传文件类型控制
        if (commandNo.equals("0B")) {
            return agreement = buildConfigOB((Config0B) config);
        }
        // 配置-设备ID
        if (commandNo.equals("0C")) {
            return agreement = buildConfigOC((Config0C) config);
        }
        // 配置-删除存储区采集数据
        if (commandNo.equals("0D")) {
            return agreement = buildConfigOD((Config0D) config);
        }

        return null;
    }

    /**
     * 发送配置命令
     * @param agreement 命令
     * @return ResultData
     */
    public ResultData sendConfigCommand(AgreementStructure agreement) {
        /* 发送命令 */
        super.sendCommand(agreement);

        ResultData result = new ResultData(Boolean.TRUE);
        result.setResult(Boolean.TRUE);
        result.setInfo("发送指令成功！");
        result.setData(null);
        return result;
    }

    /**
     * 获取 响应命令
     * @param agreement 收到的回复信息
     */
    public void getApplyCommand(AgreementStructure agreement) {
        if (agreement == null || StringUtil.isEmpty(agreement.getData()) || agreement.getData().length() < 4) {
            log.error("解析配置参数回复错误！");
        }

        // 获取 命令标编号
        String commandNo = agreement.getData().substring(0, 2);
        // 获取 执行结果
        String result = agreement.getData().substring(2, 4);
    }


    /************************************************************
     * 创建命令：配置-主机信息 (01)
     * @param config 配置-主机信息
     * @return AgreementStructure
     */
    private AgreementStructure buildInfo(InfoConfig config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        // 设置内容（0-全部）
        sbuHexData.append(CodeConvertor.intToHexString(config.getSettingType(), 1));
        // 服务器IP
        sbuHexData.append(CodeConvertor.ip2HexString(config.getServerIp()));
        // 服务器端口
        sbuHexData.append(CodeConvertor.intToHexString(config.getServerPort(), 2));
        // 设备Ip
        sbuHexData.append(CodeConvertor.ip2HexString(config.getEquipmentIp()));
        // 设备-端口
        sbuHexData.append(CodeConvertor.intToHexString(config.getEquipmentPort(), 2));
        // 设备-掩码
        sbuHexData.append(CodeConvertor.ip2HexString(config.getEquipmentMask()));
        // 设备-网关
        sbuHexData.append(CodeConvertor.ip2HexString(config.getEquipmentGateway()));
        // 设备编号（与拨码开关对应）
        sbuHexData.append(CodeConvertor.intToHexString(config.getEquipmentNumber(), 1));
        // 段号
        sbuHexData.append(config.getTrainPart1No());
        // 车列
        sbuHexData.append(config.getTrainPart2No());
        // 车号
        sbuHexData.append(config.getTrainPart3No());
        // 1车IP
        sbuHexData.append(CodeConvertor.ip2HexString(config.getCarNo1Ip()));
        // 6车IP
        sbuHexData.append(CodeConvertor.ip2HexString(config.getCarNo6Ip()));
        // 备用-服务器IP
        sbuHexData.append(CodeConvertor.ip2HexString(config.getBackupServerIp()));
        // 备用-设备IP
        sbuHexData.append(CodeConvertor.ip2HexString(config.getBackupEquipmentIp()));
        // 备用-设备网关
        sbuHexData.append(CodeConvertor.ip2HexString(config.getBackupEquipmentGateway()));

        /* 构造 协议结构体 */
        AgreementStructure agreement = getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令：配置-采集策略 (02)
     * @param config 配置-采集策略
     * @return AgreementStructure
     */
    private AgreementStructure buildCollectionStrategy(CollectionStrategyConfig config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        // 部件(1)
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategy(), 1));
        // 部件-速度
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategySpeed(), 1));
        // 部件-速度波动范围
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyWave(), 1));
        // 部件-采集时间（触发时间，单位：秒）
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyTriggerTime(), 1));
        // 部件-采集时间（持续时间，单位：秒）
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyContinueTime(), 1));
        // 部件-频率单位
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyFrequencyUnit(), 1));
        // 部件-频率
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyFrequency(), 1));
        // 部件-最大采集次数
        sbuHexData.append(CodeConvertor.intToHexString(config.getPartsStrategyCollectionNumber(), 1));

        // 波磨(2)
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategy(), 1));
        // 波磨-速度
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategySpeed(), 1));
        // 波磨-速度波动范围
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategyWave(), 1));
        // 波磨-采集时间（触发时间，单位：秒）
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategyTriggerTime(), 1));
        // 波磨-采集时间（持续时间，单位：秒）
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategyContinueTime(), 1));
        // 波磨-频率单位
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategyFrequencyUnit(), 1));
        // 波磨-频率
        sbuHexData.append(CodeConvertor.intToHexString(config.getCorrugationStrategyFrequency(), 1));

        // 温度(3)
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategy(), 1));
        // 温度-速度(FF)
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategySpeed(), 1));
        // 温度-速度波动范围(FF)
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategyWave(), 1));
        // 温度-采集时间（触发时间，单位：秒）(FF)
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategyTriggerTime(), 1));
        // 温度-采集时间（持续时间，单位：秒）(FF)
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategyContinueTime(), 1));
        // 温度-频率单位
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategyFrequencyUnit(), 1));
        // 温度-频率
        sbuHexData.append(CodeConvertor.intToHexString(config.getTemperatureStrategyFrequency(), 1));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令：配置-故障分级 (03)
     * @param config 配置-故障分级
     * @return AgreementStructure
     */
    private AgreementStructure buildFaultGrade(FaultGradeConfig config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        // 故障分级类型
        sbuHexData.append(CodeConvertor.intToHexString(config.getType(), 1));
        // 长度
        sbuHexData.append(CodeConvertor.intToHexString(config.getLength(), 2));
        // 数据
        sbuHexData.append(CodeConvertor.string2HexString(config.getData()));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令-配置-系统时间 (04)
     * @param config 通讯协议命令-参数设置-04：时间
     * @return AgreementStructure
     */
    private AgreementStructure buildSystemTime(SystemTimeConfig config) {
        Calendar calendar = Calendar.getInstance();

        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();
        // 命令
        sbuHexData.append(config.getCommonNo());
        // 年
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.YEAR)- 2000, 1));
        // 月
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.MONTH) + 1, 1));
        // 日
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.DAY_OF_MONTH), 1));
        // 时
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.HOUR_OF_DAY), 1));
        // 分
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.MINUTE), 1));
        // 秒
        sbuHexData.append(CodeConvertor.intToHexString(calendar.get(Calendar.SECOND), 1));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令：配置-波磨设置 (05)
     * @param config 配置-波磨设置
     * @return AgreementStructure
     */
    private AgreementStructure buildCorrugation(CorrugationConfig config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        // 485-1的I型
        sbuHexData.append(CodeConvertor.intToHexString(config.getCom1Model1(), 1));
        // 485-1的II型
        sbuHexData.append(CodeConvertor.intToHexString(config.getCom1Model2(), 1));
        // 485-2的I型
        sbuHexData.append(CodeConvertor.intToHexString(config.getCom2Model1(), 1));
        // 485-2的II型
        sbuHexData.append(CodeConvertor.intToHexString(config.getCom2Model2(), 1));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令：配置-心跳设置 (06)
     * @param config 配置-心跳设置
     * @return AgreementStructure
     */
    private AgreementStructure buildHeartbeat(HeartbeatConfig config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        // 心跳间隔时间（单位：秒）
        sbuHexData.append(CodeConvertor.intToHexString(config.getIntervalTime(), 1));
        // 检测断开次数
        sbuHexData.append(CodeConvertor.intToHexString(config.getBreakCount(), 1));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令-配置：前置采集重置
     */
    private AgreementStructure buildConfigOA(Config0A config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        sbuHexData.append(config.getData());

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令-配置：上传文件类型控制
     */
    private AgreementStructure buildConfigOB(Config0B config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        StringBuilder sbuData = new StringBuilder(config.getBit7()).append(config.getBit6());
        sbuData.append(config.getBit5()).append(config.getBit4());
        sbuData.append(config.getBit3()).append(config.getBit2());
        sbuData.append(config.getBit1()).append(config.getBit0());
        sbuHexData.append(CodeConvertor.bin2HexString(sbuData.toString()));

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令-配置：设备ID
     */
    private AgreementStructure buildConfigOC(Config0C config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        sbuHexData.append(config.getData());

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }

    /**
     * 创建命令-配置：删除存储区采集数据
     */
    private AgreementStructure buildConfigOD(Config0D config) {
        /* 构造 协议内容 */
        StringBuilder sbuHexData = new StringBuilder();

        // 命令
        sbuHexData.append(config.getCommonNo());
        sbuHexData.append(config.getData());

        /* 构造 协议结构体 */
        AgreementStructure agreement = this.getAgreement(config.getEquipmentMacAddr(), sbuHexData.toString());
        return agreement;
    }


    /************************************************************
     * 构造协议内容
     * @param equipmentId 设备标识
     * @param data 数据
     * @return AgreementStructure
     */
    private AgreementStructure getAgreement(String equipmentId, String data) {
        AgreementStructure agreement = new AgreementStructure();

        // 前导码(4)
        agreement.setPc(AgreementConstant.PC_VALUE);
        // 帧头(1)
        agreement.setSd(AgreementConstant.SD_VALUE);
        // 控制(1)
        agreement.setFc(AgreementCommandEnum.S_02.getValue());
        // MAC地址(6)
        agreement.setAddr(equipmentId);
        // 序号(1)
        // agreement.setSeq(CodeConvertor.intToHexString(1, 1));
        agreement.setSeq(super.getEquipmentSeq(agreement.getAddr()));
        // 长度(2)
        agreement.setLen(CodeConvertor.intToHexString(data.length()/2, 2));
        // 数据(N)
        agreement.setData(data);
        // 校验(2)
        String crcValue = CRC16M.calculateCrc(agreement);
        agreement.setFcs(crcValue);
        // 帧尾(1)
        agreement.setFs(AgreementConstant.FS_VALUE);

        return agreement;
    }

}